home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / xmsif140.zip / XMSIF.DOC < prev    next >
Text File  |  1991-12-08  |  42KB  |  927 lines

  1.                                  XMSIF
  2.                       C Interface to XMS Functions
  3.                            XMSIF version 1.4
  4.                           by James W. Birdsall
  5.                                 12/08/91
  6.  
  7.  
  8. 0. CONTENTS
  9. -----------
  10.  
  11.    0.     CONTENTS
  12.    I.     INTRODUCTION
  13.     I.1    WHAT IS SUPPORTED
  14.     I.2    COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  15.    II.    COMPILING AND LINKING WITH THE LIBRARIES
  16.     II.1   WITH C
  17.     II.2   WITH C++
  18.     II.3   XMSTEST, THE EXAMPLE PROGRAM
  19.    III.   PROGRAMMING WITH XMSIF
  20.     III.1  INITIALIZING THE LIBRARY
  21.     III.2  ORDINARY USE
  22.     III.3  TIPS ON USING EMBS
  23.     III.4  TIPS ON USING UMBS
  24.     III.5  OTHER TIPS
  25.     III.6  FUNCTION GROUPINGS
  26.    IV.    LIBRARY REFERENCE
  27.     IV.1   GLOBAL VARIABLES
  28.     IV.2   EMB FUNCTIONS
  29.     IV.3   UMB FUNCTIONS
  30.    V.     ERROR CODES
  31.     V.1    INTERNAL ERRORS
  32.     V.2    XMS DRIVER ERRORS
  33.    VI.    THE END
  34.     VI.1   ACKNOWLEDGEMENTS
  35.  
  36.  
  37. I. INTRODUCTION
  38. ---------------
  39.  
  40.    XMSIF provides a high-level interface to XMS control functions for
  41. common operations such as allocating and freeing XMS extended memory
  42. blocks (EMBs) and upper memory blocks (UMBs), and copying data to and
  43. from EMBs. A raw interface to the driver has been included to allow more
  44. convenient access to driver functions not otherwise supported.
  45.  
  46.    XMSIF is written in assembly language for speed and assembled with
  47. Borland's Turbo Assembler (TASM) 2.5. The source code is not compatible
  48. with the Microsoft Assembler (MASM).
  49.  
  50.  I.1 WHAT IS SUPPORTED
  51.  ---------------------
  52.  
  53.    XMSIF expressly supports the Microsoft eXtended Memory Specification
  54. (XMS) version 2.0. Versions below 2.0 are not supported. Versions above
  55. 2.0 are supported as 2.0.
  56.  
  57.    XMSIF supports tiny, small, medium, compact, large, and huge memory
  58. models. The small model library supports both tiny and small models, so
  59. no library is provided specifically for tiny model.
  60.  
  61.    XMSIF supports any version of Turbo C, Turbo C++, or Borland C++, in
  62. both C and C++ modes, and Microsoft C 6.00 and 6.00A. XMSIF has been
  63. tested with Borland C++ 2.0, Turbo C 2.0, and Microsoft C 6.00A in all
  64. of the supported memory models. XMSIF should work with earlier versions
  65. of Microsoft C and any other MS-DOS C compiler that 1) uses compatible
  66. parameter passing and return methods and 2) can use standard-format
  67. libraries.
  68.  
  69.  I.2 COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  70.  -----------------------------------------------
  71.  
  72.    XMSIF is not in the public domain. All the files are copyright 1991
  73. by James W. Birdsall, all rights reserved. Permission is granted to do
  74. the following:
  75.  
  76.         You may freely redistribute this archive, so long as it contains
  77.         all the files listed in the file MANIFEST, intact and
  78.         unmodified.
  79.  
  80.         You may use the libraries in programs for your own use. You may
  81.         not distribute programs linked with these libraries.
  82.  
  83.    Payment of the $5 shareware registration fee ($50 for commercial use)
  84. grants the following license, in addition to the permissions listed
  85. above:
  86.  
  87.         You may request the source to XMSIF. You may modify the source
  88.         as necessary for use in your programs. However, you may not
  89.         redistribute either the original or modified source. There is no
  90.         additional charge for source.
  91.  
  92.         You may distribute programs linked with either the original
  93.         libraries or libraries generated from source you have modified,
  94.         without royalty, provided you (a) do not alter or remove
  95.         copyright notices contained therein and (b) you indemnify, hold
  96.         harmless, and defend the author from and against any claims or
  97.         lawsuits, including attorney's fees, that arise or result from
  98.         the use or distribution of your software product. 
  99.  
  100. For the purposes of this license, commercial use is defined as use by an
  101. incorporated entity in a software product that is regarded as the
  102. product of the corporation, no matter how the software product is
  103. distributed, but only if 100 or more copies of the product are expected
  104. to be made.
  105.  
  106.    Registered users will also receive update notices and bug reports,
  107. and are entitled to use future versions without further payment.
  108.  
  109.    The contents of the distribution archive, and all other related
  110. files, information, and services are provided "as is" and without
  111. warranty. To the extent permitted by applicable law, the author
  112. disclaims all warranties, express or implied, including but not limited
  113. to, any implied warranty of merchantability or fitness for a particular
  114. purpose. While effort has been made to ensure that the files, information,
  115. and services are accurate and correct, the author shall not be liable
  116. for damages arising out of the use of or inability to use this product,
  117. including but not limited to, loss of profit, data, or use of this
  118. software, or special, incidental, or consequential damages or other
  119. similar claims, even if the author has been specifically advised of the
  120. possibility of such damages. Some states do not allow the exclusion of
  121. incidental or consequential damages, so the foregoing limitation may not
  122. apply to you.
  123.  
  124.    Information on contacting the author is provided at the end of this
  125. file.
  126.  
  127.  
  128. II. COMPILING AND LINKING WITH THE LIBRARIES
  129. --------------------------------------------
  130.  
  131.    This section describes how to use the XMSIF libraries with your
  132. programs.
  133.  
  134.    XMSIF is provided as Borland/Microsoft standard library files.
  135. Libraries are provided for small, medium, compact, large, and huge
  136. memory models (tiny model uses the small model library). The model for
  137. which a library is intended is indicated by the last letter of the
  138. filename proper, which is the same as the first letter for the model.
  139. For example, XMSIFL.LIB is the large model library.
  140.  
  141.  II.1 WITH C
  142.  -----------
  143.  
  144.    To use XMSIF in C programs, you must #include the file XMSIF.H in
  145. every source file that calls XMSIF functions, accesses XMSIF global
  146. variables, or uses #defined constants provided by XMSIF.
  147.  
  148.    The procedures for linking XMSIF with the rest of your program vary
  149. according to the compiler and method you are using. In general, you must
  150. include the appropriate library (the library corresponding to the memory
  151. model in which you have compiled the rest of your program) in the link.
  152.  
  153.    If you are compiling in the Integrated Development Environment of
  154. Turbo/Borland C[++], you should include the name of the appropriate
  155. library in the project file for your program. For example, if you are
  156. working in the compact memory model, you should include XMSIFC.LIB in
  157. your project file.
  158.  
  159.    If you are using a command-line compiler (bcc, tcc, or cl) to compile
  160. and link, simply place the full name of the appropriate XMSIF library on
  161. the command line. For example, "bcc -mc foo.c xmsifc.lib" will compile
  162. the file "foo.c" in the compact model and link it with xmsifc.lib.
  163.  
  164.    If you are linking manually (using TLINK or LINK), place the name of
  165. the appropriate library in with the other libraries. For example,
  166.         tlink c0c.obj foo.obj, foo.exe, foo.map, cc.lib xmsifc.lib
  167. or
  168.         link foo.obj, foo.exe, foo.map, xmsifc.lib ;
  169. will link the object "foo.obj" with the appropriate startup object and
  170. standard library (LINK automatically includes the startup object and
  171. standard library, so it is not necessary to explicitly include them) and
  172. the compact model XMSIF library.
  173.  
  174.  II.2 C++
  175.  --------
  176.  
  177.    To use XMSIF in C++ programs, you must #include the file XMSIF.HPP in
  178. every file that calls XMSIF functions, accesses XMSIF global variables,
  179. or uses #defined constants provided by XMSIF. Be careful to include
  180. XMSIF.HPP instead of XMSIF.H. If you include the wrong one, you will
  181. probably see "undefined symbol" errors when linking.
  182.  
  183.    Otherwise, the procedures for using XMSIF with C++ programs are the
  184. same as for using it with C programs.
  185.  
  186.  II.3 XMSTEST, THE EXAMPLE PROGRAM
  187.  ---------------------------------
  188.  
  189.    A large and complete example program and tester, XMSTEST, has been
  190. included in this distribution. It can be compiled in any of the
  191. supported memory models, with either Borland or Microsoft compilers.
  192.  
  193.    The test program has four source files: XMSTEST.C, XMSTEST2.C,
  194. XMSTEST3.C, and TESTUTIL.C, and two header files: XMSTEST.H and
  195. TESTUTIL.H. When compiling in tiny model with Borland compilers, an
  196. additional source file, STACK.ASM, is needed. STACK.OBJ, which is
  197. STACK.ASM pre-assembled, has been included for those who do not have
  198. assemblers.
  199.  
  200.    Example makefiles have been included for Borland and Microsoft
  201. compilers. EXMAKEBC is the example makefile for Borland C++ 2.0,
  202. EXMAKETC is the example makefile for Turbo C[++], and EXMAKEMS is the
  203. example makefile for Microsoft C. Complete instructions for making the
  204. example program and using the example makefiles are included at the
  205. beginning of each makefile. More information about the program is also
  206. included at the beginning of XMSTEST.C.
  207.  
  208.    XMSTEST requires a single free EMB of at least 81,920 bytes in order
  209. to perform the copy-function tests. It requires at least one free UMB in
  210. order to perform all the UMB-function tests. If your system does not
  211. support UMBs, XMSTEST will note this fact and skip inappropriate
  212. UMB-function tests. If your system does support UMBs but none are free,
  213. XMSTEST will assume that your system does not support UMBs and will also
  214. skip inappropriate UMB-function tests. XMSTEST also requires at least
  215. 165,000 bytes of available conventional memory to run.
  216.  
  217.    XMSTEST may require the command-line parameter "-q" to run on your
  218. system. A full explanation of this parameter and what it does may be
  219. found at the beginning of XMSTEST.C.
  220.  
  221.  
  222. III. PROGRAMMING WITH XMSIF
  223. ---------------------------
  224.  
  225.    This section describes how to make XMSIF calls in your program, and
  226. details various tricks and tips which you may find useful.
  227.  
  228.  III.1 INITIALIZATION
  229.  --------------------
  230.  
  231.    The library initialization function XMMlibinit() _must_ be called
  232. before any other XMSIF calls are made. All other XMSIF functions are
  233. guaranteed to fail if called before XMMlibinit(). XMMlibinit()
  234. determines whether an XMS driver is present and sets up various internal
  235. and global variables necessary to the functioning of XMSIF.
  236.  
  237.  
  238.  III.2 ORDINARY USE
  239.  ------------------
  240.  
  241.    XMSIF provides several sets of functions. First, there is a set of
  242. functions which are intended to be orthogonal with the standard C
  243. functions malloc() and free(), and the Borland/Turbo C[++] function
  244. coreleft(), for EMBs. These functions are XMMalloc(), XMMfree(),
  245. XMMcoreleft(), and XMMallcoreleft().
  246.  
  247.    Second, there is a group of functions for copying data to and from
  248. EMBs. These functions are XMMcopyto(), XMMcopyfrom(), _XMMcopy(),
  249. XMMicopyto(), XMMicopyfrom(), and _XMMicopy().
  250.  
  251.    Third, there is a group of miscellaneous functions: XMMlibinit(),
  252. XMMgetversion(), and XMMrawcall().
  253.  
  254.    Finally, there is a set of functions which are intended to be
  255. orthogonal with the standard C functions malloc() and free(), and the
  256. Borland/Turbo C[++] function coreleft(), for UMBs. These functions are
  257. UMBalloc(), UMBfree(), UMBcoreleft(), and UMBallcoreleft(). For details
  258. on these functions and all the others listed above, see section IV.2.
  259.  
  260.    To use EMBs (Extended Memory Blocks), first it is necessary to
  261. allocate some. This is done with XMMalloc(), which takes a size in bytes
  262. and returns a handle which will be used to reference the allocated
  263. memory. EMBs are subject to fragmentation problems; it is not possible
  264. to allocate with XMMalloc() more extended memory than is in the largest
  265. free block. The size of the largest free block, in bytes, is returned by
  266. XMMcoreleft(). The total of all free EMBs is returned by
  267. XMMallcoreleft(). Other considerations about using EMBs are discussed in
  268. section III.3 below.
  269.  
  270.    The only way to get data to or from an EMB is via the XMS driver's
  271. copying functions. The XMSIF copying functions provide handy interfaces
  272. to the underlying driver functions and provide extra processing to
  273. remove some of the limitations on the driver functions (such as the
  274. inability to copy an odd number of bytes).
  275.  
  276.    The miscellaneous functions listed above initialize XMSIF
  277. (XMMlibinit(), see section III.1), return the XMS version implemented by
  278. the driver (XMMgetversion()), and allow programs to call the driver more
  279. directly, specifying values for all the relevant registers
  280. (XMMrawcall()).
  281.  
  282.    Finally, to use UMBs (Upper Memory Blocks, which may exist in unused
  283. spaces between 640K and 1M), first it is necessary to allocate one (or
  284. more). This is done with UMBalloc(), which takes a size in bytes and
  285. returns a far pointer to the UMB. UMBs are subject to fragmentation
  286. problems; it is not possible to allocate with UMBalloc() more memory
  287. than is in the largest free block. The size of the largest free block,
  288. in bytes, is returned by UMBcoreleft(). The total of all free UMBs is
  289. returned by UMBallcoreleft(). Other problems with using UMBs are
  290. discussed in section III.4 below. Since UMBs can be accessed directly,
  291. no copying functions are provided for them.
  292.  
  293.    Many functions return a status directly. For those functions, a
  294. return value of 0 indicates success and a return value of XMMOOPS
  295. indicates failure. The global variable _XMMerror contains an error code
  296. which gives further information on why the function failed, or has value
  297. 0 if the function succeeded. Many functions return some other value
  298. instead of a status code (0 or XMMOOPS). In these cases, the value of
  299. _XMMerror should be checked upon return. The recommended method of
  300. error-checking is indicated for each function in section IV.2 below.
  301.  
  302.  III.3 TIPS ON USING EMBS
  303.  ------------------------
  304.  
  305.    As mentioned above, EMBs are subject to fragmentation problems, and
  306. the limit on allocation is the size of the largest free block. This has
  307. some interesting side effects. For one, there is no single measure of
  308. free extended memory. In some cases, the size of the largest free block
  309. will be most useful, in other cases, the total of all free blocks. Thus,
  310. both XMMcoreleft() and XMMallcoreleft() are provided. But a consequence
  311. of having multiple measures is that allocations may change the values in
  312. unanticipated ways. For example, while any allocation will change the
  313. total of all free blocks, it may or may not change the size of the
  314. largest free block depending on the size of the allocation request and
  315. the allocation strategy followed by the XMS driver. For example, if the
  316. allocation request is small enough to fit into a smaller free block, the
  317. XMS driver may perform the allocation from the smaller block, leaving
  318. the size of the largest free block unchanged. Or it may always perform
  319. allocations from the largest free block, in which case the size of the
  320. largest free block will change. In summary, do not depend on the size of
  321. the largest free block changing when you allocate extended memory.
  322.  
  323.    Furthermore, not all XMS drivers behave in exactly the same way.
  324. While writing XMSTEST, I observed distinct differences between QEMM 5.12
  325. and HIMEM.SYS 2.77. The most obvious difference is that when allocating
  326. under QEMM, the total of all free blocks drops by the size of the
  327. allocation rounded up to the nearest 16K, instead of the size rounded up
  328. to the nearest 1K (the minimum allocation unit for EMBs). This is
  329. probably related to QEMM's support of EMS, which has a minimum
  330. allocation unit of 16K. XMSTEST's -q parameter is a direct response to
  331. this difference in behavior. In summary, do not depend on the total of
  332. all free blocks changing by the amount you think it will.
  333.  
  334.    Finally, there are some speed considerations when using EMBs. For
  335. maximum speed, copy the largest blocks you can. Each copy of an even
  336. number of bytes makes one call to the XMS driver. Each copy of an odd
  337. number of bytes makes two calls to the XMS driver. And each copy of a
  338. single byte requires no fewer than three calls to the XMS driver in
  339. order to reliably copy the desired byte without corrupting surrounding
  340. data (remember that the XMS driver itself can only copy even numbers of
  341. bytes). To get a good idea of relative speeds of various sizes of
  342. copies, run XMSTEST -- it performs some speed tests, returning times in
  343. ticks (at 18.2 ticks per second). Large copies may be hundreds of times
  344. faster than small copies. If you have to make lots of small copies, try
  345. using the interval copy functions (_XMMicopy() et al.). They make the
  346. same number of calls to the XMS driver, but the loops are tightly coded
  347. in assembly and are marginally faster than performing the same loop
  348. yourself. And, as a last consideration, note that different XMS drivers
  349. may be faster or slower. Results from XMSTEST showed that QEMM was
  350. roughly 40% faster than HIMEM.SYS.
  351.  
  352.  III.4 TIPS ON USING UMBS
  353.  ------------------------
  354.  
  355.    It is probably better not to use UMBs if there isn't a powerful
  356. reason to do so. UMBs are not present on many systems, may be all used
  357. on other systems, and some XMS drivers have buggy UMB support functions.
  358.  
  359.    UMBs are blocks of memory between 640K (the top of conventional
  360. memory) and 1M (in general, the top of memory addressable in real mode).
  361. Systems based on the 80286 do not have UMBs unless there is special
  362. hardware support on the motherboard or elsewhere. Even if the hardware
  363. support is present, an XMS driver is also required to provide the UMB
  364. management functions. Systems based on the 80386 and up do not require
  365. the hardware support, but do require a driver (such as QEMM, EMM386.SYS,
  366. 386-to-the-Max, etc.) which uses the processor's on-board memory mapping
  367. capability to make extended memory appear between 640K and 1M, in unused
  368. holes between video memory, ROMs, and anything else inhabiting that
  369. space. Then they may require a separate XMS driver to actually provide
  370. the UMB management functions. QEMM and 386-to-the-Max include XMS
  371. drivers within themselves; EMM386.SYS requires HIMEM.SYS.
  372.  
  373.    Even if the system has the requisite support and drivers, UMBs may
  374. not be available to your application. DOS 5.0, for example, depending on
  375. the configuration, may allocate all UMBs to itself.
  376.  
  377.    Lastly, some XMS drivers have buggy UMB support functions. While
  378. testing XMSIF, I discovered that QEMM 5.12 may return a random error
  379. code when there are no more free UMBs. In fact, it may not return an
  380. error code at all -- it may leave the contents of that register
  381. untouched. Various measures to combat this problem have been taken
  382. within XMSIF with sufficient success that XMSTEST can perform the
  383. UMB-function tests under QEMM 5.12 correctly, but other XMS drivers may
  384. have other bugs. In summary, I would advise that you avoid the use of
  385. UMBs unless there is a powerful reason to do so, and even then your
  386. program should be ready to deal with error returns or unusual results.
  387.  
  388.  III.5 OTHER TIPS
  389.  ----------------
  390.  
  391.    Neither EMBs nor UMBs are deallocated automatically when a program
  392. exits. If the program does not deallocate EMBs or UMBs that it has
  393. allocated, those EMBs and/or UMBs are stuck, not available to any other
  394. program until the machine is rebooted. Under normal circumstances, it is
  395. easy enough to free EMBs and UMBs when they are no longer needed.
  396. However, an emergency exit due to the user hitting control-break or due
  397. to a hardware error (e.g. the famous "Abort, Retry, Fail?") can cause
  398. EMBs or UMBs to become stuck unless your program takes special measures
  399. to intercept these errors and perform cleanup before exiting. There are
  400. a number of ways to do this and they vary from compiler to compiler.
  401. Look for functions named things like ctrlbrk(), harderr(), and signal().
  402.  
  403.    If you are copying array elements, XMMicopyto(), XMMicopyfrom(), or
  404. _XMMicopy() may be more efficient. These functions allow copying of
  405. elements of fixed size which are separated by gaps also of fixed size.
  406. For example, if you have an array of integers and wish to copy all the
  407. even-indexed elements (a[0], a[2], a[4], etc.), these functions are
  408. faster than calling a standard copying function (XMMcopyto(),
  409. XMMcopyfrom(), or _XMMcopy()) from within a loop.
  410.  
  411.  III.6 FUNCTION GROUPING
  412.  -----------------------
  413.  
  414.    The XMSIF functions have been arranged in the library in such a way
  415. as to reduce the number of unnecessary functions linked into your
  416. program. There are currently two groups:
  417.  
  418.                 FUNCTIONS                               VARIABLES
  419.                 ---------                               ---------
  420. GROUP 1:        XMMlibinit(), XMMgetversion(),          _XMMerror, _XMMversion,
  421.                 XMMcoreleft(), XMMallcoreleft(),        _xmsif_vers_vers,
  422.                 XMMalloc(), XMMfree(), _XMMcopy(),      _xmsif_vers_date,
  423.                 _XMMicopy(), XMMrawcall()               _xmsif_vers_time
  424.  
  425. GROUP 2:        UMBcoreleft(), UMBallcoreleft(),        none
  426.                 UMBalloc(), UMBfree()
  427.  
  428. If your program references any of the functions or variables in a group,
  429. all the functions and variables in that group will be linked in. Note
  430. that group one will always be linked, since it contains XMMlibinit(),
  431. which all XMSIF-using programs must call.
  432.  
  433.  
  434. IV. LIBRARY REFERENCE
  435. ---------------------
  436.  
  437.  IV.1 GLOBAL VARIABLES
  438.  ---------------------
  439.  
  440.   _XMMerror
  441.   ---------
  442.  
  443.    unsigned char const _XMMerror;
  444.  
  445.    _XMMerror contains the error code from the last XMSIF call. If the
  446. call succeeded, _XMMerror will be 0. If the call failed because the XMS
  447. driver returned an error, _XMMerror contains the error code returned by
  448. the XMS driver. If the call failed because XMSIF detected an error
  449. internally, _XMMerror contains an internal error code. A list of error
  450. code values, their meanings, and #defined constants for them is in
  451. section V.
  452.  
  453.   _XMMversion
  454.   -----------
  455.  
  456.    unsigned int const _XMMversion;
  457.  
  458.    _XMMversion contains the XMS version implemented by the XMS driver in
  459. packed BCD format. For example, if the XMS version is 2.0, the value of
  460. _XMMversion will be 0x0200. The high byte of _XMMversion represents two
  461. digits to the left of the decimal point (one digit per nibble) and the
  462. low byte represents two digits to the right of the decimal point (again,
  463. one digit per nibble). This value is the same as that returned by
  464. XMMgetversion().
  465.  
  466.   xmsif_vers_vers, xmsif_vers_date, xmsif_vers_time
  467.   -------------------------------------------------
  468.  
  469.    char const xmsif_vers_vers[];
  470.    char const xmsif_vers_date[];
  471.    char const xmsif_vers_time[];
  472.  
  473.    These are null-terminated strings containing information about the
  474. name and version of the library, the date of assembly, and the time of
  475. assembly, respectively.
  476.  
  477.  IV.2 EMB FUNCTIONS
  478.  ------------------
  479.  
  480.   _XMMcopy() - copy data
  481.   ----------
  482.  
  483.    int _XMMcopy(unsigned long clen,
  484.                 int shan, unsigned long soff,
  485.                 int dhan, unsigned long doff);
  486.    int XMMcopyfrom(unsigned long clen,
  487.                    int handle, unsigned long soff,
  488.                    unsigned char far *dest);
  489.    int XMMcopyto(unsigned long clen,
  490.                  unsigned char far *src,
  491.                  int handle, unsigned long doff);
  492.  
  493.    _XMMcopy() allows painless copying from conventional memory to an
  494. EMB, from an EMB to conventional memory, from one EMB to another, or
  495. even from one point in conventional memory to another. Areas larger than
  496. 64K can be copied without special treatment. Clen bytes of data are
  497. copied. If shan is nonzero, it is assumed to be the handle of an EMB,
  498. and soff is treated as a byte offset into the EMB owned by shan. If shan
  499. is zero, soff is treated as a segment:offset far pointer to conventional
  500. memory. The pair of shan and soff indicate where the data is to be
  501. copied from (the source). Dhan and doff work similarly, but indicate
  502. where the data is to be copied to (the destination).
  503.    This function returns 0 on success or XMMOOPS on error. The specific
  504. error may be determined from _XMMerror. If clen is 0, the function
  505. returns immediately without error.
  506.  
  507.    XMMcopyfrom() is a macro which provides a convenient interface to
  508. _XMMcopy() for copying data from an EMB to conventional memory. Clen
  509. bytes of data are copied. Handle is the handle of an EMB, and soff is a
  510. byte offset into the EMB owned by handle. The pair of handle and soff
  511. indicate where the data is to be copied from. Dest is a far pointer to
  512. conventional memory and indicates where the data is to be copied to. The
  513. returns are the same as for _XMMcopy().
  514.  
  515.    XMMcopyto() is a macro which provides a convenient interface to
  516. _XMMcopy() for copying data to an EMB from conventional memory. Clen
  517. bytes of data are copied. Src is a far pointer to conventional memory
  518. and indicates where the data is to be copied from. Handle is the handle
  519. of an EMB, and doff is a byte offset into the EMB owned by handle. The
  520. pair of handle and doff indicate where the data is to be copied to. The
  521. returns are the same as for _XMMcopy().
  522.  
  523.   _XMMicopy() - copy data by intervals
  524.   -----------
  525.  
  526.    int _XMMicopy(unsigned long nelem, int elsize,
  527.                  unsigned int sskip, int shan, unsigned long soff,
  528.                  int dhan, unsigned long doff, unsigned int dskip);
  529.    int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
  530.                     int handle, unsigned long soff,
  531.                     unsigned char far *dest);
  532.    int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  533.                   unsigned char far *src,
  534.                   int handle, unsigned long doff);
  535.  
  536.    _XMMicopy() allows painless copying of array elements from
  537. conventional memory to an EMB, from an EMB to conventional memory, from
  538. one EMB to another, or even from one point in conventional memory to
  539. another. Calculation of addresses, skipping of unwanted elements, etc.,
  540. are all handled by the function. Elements spread across more than 64K
  541. or totalling more than 64K in length can be copied without special
  542. treatment.
  543.    Nelem elements are copied, each of which is elsize bytes long. If
  544. shan is nonzero, it is assumed to be the handle of an EMB, and soff is
  545. treated as a byte offset into the EMB owned by shan. If shan is zero,
  546. soff is treated as a segment:offset far pointer to conventional memory.
  547. The pair of shan and soff indicate where the data is to be copied from
  548. (the source). Dhan and doff work similarly, but indicate where the data
  549. is to be copied to (the destination). Sskip and dskip indicate the
  550. number of bytes between elements in the source and destination,
  551. respectively.
  552.    If nelem or elsize is zero, the function returns immediately without
  553. error. If nelem is one, _XMMcopy() is called internally. Elsize must be
  554. in the range 0 through 16384, or the function will return with error
  555. XMM_ELTOOBIG (in _XMMerror). Sskip and dskip must both be in the range 0
  556. through 32768, or the function will return with error XMM_SKTOOBIG (in
  557. _XMMerror).
  558.    This function returns 0 on success or XMMOOPS on error. The specific
  559. error may be determined from _XMMerror.
  560.  
  561.    XMMicopyfrom() is a macro which provides a more convenient interface
  562. to _XMMicopy() for copying data from an EMB to conventional memory with
  563. sskip equal to dskip. Nelem elements are copied, each of which is elsize
  564. bytes long. Handle is the handle of an EMB, and soff is a byte offset
  565. into the EMB owned by handle. The pair of handle and soff indicate where
  566. the data is to be copied from. Dest is a far pointer to conventional
  567. memory and indicates where the data is to be copied to. Byteskip is the
  568. number of bytes between elements, the same for both source and
  569. destination. The returns are the same as for _XMMicopy().
  570.  
  571.    XMMicopyto() is a macro which provides a more convenient interface
  572. to _XMMicopy() for copying data to an EMB from conventional memory with
  573. sskip equal to dskip. Nelem elements are copied, each of which is elsize
  574. bytes long. Src is a far pointer to conventional memory and indicates
  575. where the data is to be copied from. Handle is the handle of an EMB, and
  576. doff is a byte offset into the EMB owned by handle. The pair of handle
  577. and doff indicate where the data is to be copied to. Byteskip is the
  578. number of bytes between elements, the same for both source and
  579. destination. The returns are the same as for _XMMicopy().
  580.  
  581.   XMMallcoreleft() - get total of all free EMBs
  582.   ----------------
  583.  
  584.    unsigned long XMMallcoreleft(void);
  585.    unsigned long XMMcoreleft(void);
  586.  
  587.    XMMallcoreleft() returns the total size of all free EMBs, in bytes.
  588. Note that when all EMBs have been allocated, the driver itself returns
  589. an error (0xA0, XMM_NOFREEX). This behavior is masked by
  590. XMMallcoreleft() -- if there are no free EMBs, XMMallcoreleft() returns
  591. 0L, not an error. _XMMerror should be checked after calling this
  592. function.
  593.  
  594.    XMMcoreleft() returns the size of the largest free EMB, in bytes.
  595. Note that when all EMBs have been allocated, the driver itself returns
  596. an error (0xA0, XMM_NOFREEX). This behavior is masked by XMMcoreleft() --
  597. if there are no free EMBs, XMMcoreleft() returns 0L, not an error.
  598. _XMMerror should be checked after calling this function.
  599.  
  600.   XMMalloc() - allocate EMB
  601.   ----------
  602.  
  603.    int XMMalloc(unsigned long bytes);
  604.  
  605.    This function allocates an EMB. It takes the given number of bytes
  606. and rounds it up to the nearest kilobyte, then allocates an EMB that
  607. many kilobytes in size. It returns the EMB handle assigned by the XMS
  608. driver. _XMMerror should be checked after calling this function.
  609.    Note that EMBs cannot be allocated in units smaller than a kilobyte
  610. (1024 bytes). Requesting one byte will allocate 1K; 1025 bytes will
  611. allocate 2K. Requesting zero bytes allocates a handle but no memory.
  612.    Note that it is not possible to allocate in one XMMalloc() call more
  613. extended memory than is in the largest free EMB. This is a limitation of
  614. the XMS driver. See section III.3 above for more information on EMB
  615. allocation limitations.
  616.  
  617.   XMMcopyfrom() - copy data from EMB
  618.   -------------
  619.  
  620.    int XMMcopyfrom(unsigned long clen,
  621.                    int handle, unsigned long soff,
  622.                    unsigned char far *dest);
  623.  
  624.    See _XMMcopy().
  625.  
  626.   XMMcopyto() - copy data to EMB
  627.   -----------
  628.  
  629.    int XMMcopyto(unsigned long clen,
  630.                  unsigned char far *src,
  631.                  int handle, unsigned long doff);
  632.  
  633.    See _XMMcopy();
  634.  
  635.  
  636.   XMMcoreleft() - get size of largest free EMB
  637.   -------------
  638.  
  639.    unsigned long XMMcoreleft(void);
  640.  
  641.    See XMMallcoreleft().
  642.  
  643.   XMMfree() - deallocate an EMB
  644.   ---------
  645.  
  646.    int XMMfree(int handle);
  647.  
  648.    This function accepts an EMB handle (as returned by XMMalloc() or
  649. otherwise obtained from the XMS driver) and releases it and the EMB
  650. associated with it (if any). This function returns 0 on success or
  651. XMMOOPS on error. The specific error may be determined from _XMMerror.
  652.  
  653.   XMMgetversion() - obtain XMS version implemented by XMS driver
  654.   ---------------
  655.  
  656.    int XMMgetversion(void);
  657.  
  658.    This function returns the XMS version implemented by the XMS driver.
  659. The version number is in packed BCD format as in the global variable
  660. _XMMversion, and is in fact the same value. _XMMerror should be checked
  661. after calling this function.
  662.  
  663.   XMMicopyfrom() - copy data by intervals from EMB
  664.   --------------
  665.  
  666.    int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
  667.                     int handle, unsigned long soff,
  668.                     unsigned char far *dest);
  669.  
  670.    See _XMMicopy().
  671.  
  672.   XMMicopyto() - copy data by intervals to EMB
  673.   ------------
  674.  
  675.    int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  676.                   unsigned char far *src,
  677.                   int handle, unsigned long doff);
  678.  
  679.    See _XMMicopy().
  680.  
  681.   XMMlibinit() - initialize XMSIF
  682.   ------------
  683.  
  684.    int XMMlibinit(void);
  685.  
  686.    XMMlibinit() initializes XMSIF. Any other XMSIF function will return
  687. with error XMM_NOINIT (in _XMMerror) if called before XMMlibinit() has
  688. been called. This function returns 0 on success, XMMOOPS on error, or
  689. NOXMM if no XMS driver is detected. The specific error may be determined
  690. from _XMMerror.
  691.  
  692.   XMMrawcall() - call XMS driver directly
  693.   ------------
  694.  
  695.    int XMMrawcall(struct XMMregs *regs);
  696.  
  697.    This function is a raw interface directly to the XMS driver. The
  698. XMMregs structure has fields for the AX, BX, DX, SI, and DS registers,
  699. which are the only registers used as parameters for calls to the XMS
  700. driver. The values in the structure are placed in the appropriate
  701. registers before the XMS driver is called, and the registers are copied
  702. back into the structure after the XMS driver call returns. Check XMSIF.H
  703. or XMSIF.HPP for the exact format of the XMMregs structure.
  704.    Since the XMS specification provides a uniform error indication for
  705. all XMS calls, XMMrawcall() is able to determine if the call performed
  706. caused an error. It returns 0 on success or XMMOOPS on error. The
  707. specific error may be determined from _XMMerror; the error code can also
  708. be found in the low byte of the regBX field of the XMMregs structure.
  709.  
  710.  IV.3 UMB FUNCTIONS
  711.  ------------------
  712.  
  713.   UMBallcoreleft() - get total of all free UMBs
  714.   ----------------
  715.  
  716.    unsigned long UMBallcoreleft(void);
  717.    unsigned long UMBcoreleft(void);
  718.  
  719.    UMBallcoreleft() returns the total size of all free UMBs, in bytes.
  720. Note that when all UMBs have been allocated, the driver itself returns
  721. an error (0xB1, UMB_NOFREEUMB). This behavior is masked by
  722. UMBallcoreleft() -- if there are no free UMBs, UMBallcoreleft() returns
  723. 0L, not an error. If the XMS driver does not support UMBs at all, it
  724. returns an error (0x80, XMM_UNIMP). This is also masked by
  725. UMBallcoreleft(). Again, 0L will be returned, not an error. _XMMerror
  726. should be checked after calling this function.
  727.  
  728.    UMBcoreleft() returns the size of the largest free UMB, in bytes.
  729. Note that when all UMBs have been allocated, the driver itself returns
  730. an error (0xB1, UMB_NOFREEUMB). This behavior is masked by UMBcoreleft() --
  731. if there are no free UMBs, UMBcoreleft() returns 0L, not an error. If
  732. the XMS driver does not support UMBs at all, it returns an error (0x80,
  733. XMM_UNIMP). This is also masked by UMBallcoreleft(). Again, 0L will be
  734. returned, not an error. _XMMerror should be checked after calling this
  735. function.
  736.  
  737.   UMBalloc() - allocate UMB
  738.   ----------
  739.  
  740.    void far *UMBalloc(unsigned long bytes, unsigned long *finalsize);
  741.  
  742.    This function allocates an UMB. It takes the given number of bytes
  743. and rounds it up to the nearest multiple of 16, then allocates a UMB
  744. that many bytes in size. The actual size in bytes of the UMB allocated
  745. is returned in the unsigned long pointed to by finalsize. UMBalloc()
  746. returns a far pointer to the UMB; this pointer should be cast to a type
  747. other than void before being used to access the UMB. _XMMerror should be
  748. checked after calling this function.
  749.    Note that UMBs cannot be allocated in units smaller than a paragraph
  750. (16 bytes). Requesting one byte will allocate 16; 17 bytes will allocate
  751. 32.
  752.    Note that it is not possible to allocate in one UMBalloc() call more
  753. extended memory than is in the largest free UMB. This is a limitation of
  754. the XMS driver. See section III.4 above for more information on UMB
  755. allocation limitations.
  756.  
  757.   UMBcoreleft() - get size of largest free UMB
  758.   -------------
  759.  
  760.    unsigned long UMBcoreleft(void);
  761.  
  762.    See UMBallcoreleft().
  763.  
  764.   UMBfree() - deallocate an UMB
  765.   ---------
  766.  
  767.    int UMBfree(void far *handle);
  768.  
  769.    This function accepts a pointer to a UMB (as returned by UMBalloc())
  770. and releases that UMB. If the pointer has been modified, UMBfree()
  771. attempts to return it to canonical form before calling the XMS driver.
  772. However, for maximum reliability, UMBfree() should be called with an
  773. unmodified copy of the pointer returned by UMBalloc(). This function
  774. returns 0 on success or UMBOOPS on error. The specific error may be
  775. determined from _XMMerror.
  776.  
  777.  
  778. V. ERROR CODES
  779. --------------
  780.  
  781.    This section is a list of the error codes to which the global
  782. variable _XMMerror may be set, and the values and meanings thereof.
  783.  
  784.  V.1 INTERNAL ERRORS
  785.  -------------------
  786.  
  787.    Internal codes indicate an error detected by XMSIF itself.
  788.  
  789.    NAME                 VALUE     MEANING
  790.    ----                 -----     -------
  791.    XMM_NOINIT            0x40     XMMlibinit() must be called before any
  792.                                   other XMSIF function can be called.
  793.  
  794.    XMM_UMBHUGE           0x41     Size of UMB requested is larger than
  795.                                   XMS driver can handle (maximum UMB
  796.                                   request size is 1M).
  797.  
  798.    XMM_BADPTR            0x42     The UMB pointer passed to UMBfree()
  799.                                   is corrupt.
  800.  
  801.    XMM_ELTOOBIG          0x43     The element size passed to XMMicopyto(),
  802.                                   XMMicopyfrom(), or _XMMicopy() is too big.
  803.  
  804.    XMM_SKTOOBIG          0x44     The skip size passed to XMMicopyto(),
  805.                                   XMMicopyfrom(), or _XMMicopy() is too big.
  806.  
  807.  V.2 XMS DRIVER ERRORS
  808.  ---------------------
  809.  
  810.    These codes are defined in the XMS specification and are returned by
  811. the XMS driver. They are saved in _XMMerror by XMSIF without alteration.
  812.  
  813.    NAME                 VALUE     MEANING
  814.    ----                 -----     -------
  815.    XMM_UNIMP             0x80     Function is not implemented
  816.  
  817.    XMM_VDISK             0x81     VDISK device driver was detected
  818.  
  819.    XMM_A20ERROR          0x82     A20 error occurred
  820.  
  821.    XMM_GENERROR          0x83     General driver error occurred
  822.  
  823.    XMM_UNRECERROR        0x84     Unrecoverable driver error occurred
  824.  
  825.    XMM_NOHMA             0x90     HMA (High Memory Area) does not exist
  826.  
  827.    XMM_HMAUSED           0x91     HMA already allocated
  828.  
  829.    XMM_HMATOOBIG         0x92     Request to allocate HMA denied because
  830.                                   amount of HMA requested is less than
  831.                                   minimum parameter given to XMS driver
  832.                                   on its command line
  833.  
  834.    XMM_HMANOALLOC        0x93     HMA is not allocated
  835.  
  836.    XMM_A20STILLEN        0x94     A20 line is still enabled
  837.  
  838.    XMM_NOFREEX           0xA0     All EMBs (Extended Memory Blocks) are
  839.                                   allocated
  840.  
  841.    XMM_NOFREEXHAN        0xA1     No free EMB handles
  842.  
  843.    XMM_BADXHAN           0xA2     EMB handle is invalid
  844.  
  845.    XMM_BADSRCHAN         0xA3     Source EMB handle is invalid
  846.  
  847.    XMM_BADSRCOFF         0xA4     Source offset in EMB is beyond end of EMB
  848.  
  849.    XMM_BADDESTHAN        0xA5     Destination EMB handle is invalid
  850.  
  851.    XMM_BADDESTOFF        0xA6     Destination offset in EMB is beyond end
  852.                                   of EMB
  853.  
  854.    XMM_BADLENGTH         0xA7     Length is invalid
  855.  
  856.    XMM_COPYOVERLAP       0xA8     Overlap in copy request is invalid
  857.  
  858.    XMM_PARITY            0xA9     Parity error was detected
  859.  
  860.    XMM_NOLOCK            0xAA     EMB is not locked
  861.  
  862.    XMM_LOCKED            0xAB     EMB is locked
  863.  
  864.    XMM_TOOMANYLOCKS      0xAC     EMB lock count overflowed
  865.  
  866.    XMM_LOCKFAIL          0xAD     EMB lock failed
  867.  
  868.    XMM_UMBSMALLER        0xB0     UMB (Upper Memory Block) of size requested
  869.                                   is not available; however, a smaller UMB
  870.                                   is available
  871.  
  872.    XMM_NOFREEUMB         0xB1     All UMBs are allocated
  873.  
  874.    XMM_BADUMBHAN         0xB2     UMB handle (same as segment address of
  875.                                   start of UMB) is invalid
  876.  
  877.  
  878. VI. THE END
  879. -----------
  880.  
  881.    Technical support via email is available from the following addresses:
  882.  
  883.    INTERNET:
  884.       First choice (the following are alternate addresses for the same place):
  885.          support@picarefy.com
  886.          picarefy!support@amc.com
  887.          picarefy!support@netcom.com
  888.          picarefy!support@halcyon.com
  889.          amc-gw!picarefy!support@coco.ms.washington.edu
  890.          halcyon!picarefy!support@sumax.seattleu.edu
  891.          uunet!uw-coco!amc-gw!picarefy!support
  892.  
  893.       Second choice:
  894.          jwbirdsa@amc.com
  895.  
  896.    COMPUSERVE:
  897.       71261,1731
  898.  
  899.    AMERICA ON-LINE:
  900.       GreenTiger
  901.  
  902.    GENIE:
  903.       J.BIRDSALL2
  904.  
  905.    Registrations should be sent to:
  906.  
  907.       James W. Birdsall
  908.       11112 NE 124 LN #D204
  909.       Kirkland, WA 98034
  910.  
  911.    If you have an email address on any of the networks listed above,
  912. please include it when registering, especially if you are requesting
  913. source code. It is much easier to send the source code by email. Also,
  914. please specify what sort of archive (ZIP, ZOO, ARC, LZH, ARJ, UNIX shar)
  915. you can handle most easily.
  916.  
  917.    NOTE: IF YOU DO NOT PROVIDE AN EMAIL ADDRESS, YOU WILL ONLY RECEIVE
  918. MAJOR VERSION UPDATES. YOU WILL NOT RECEIVE MINOR VERSIONS. PLEASE
  919. PROVIDE AN EMAIL ADDRESS IF YOU HAVE ANY WAY OF DOING SO.
  920.  
  921.  VI.1 ACKNOWLEDGEMENTS
  922.  ---------------------
  923.  
  924.    Thanks to Bob Parsons of Parsons Technology Inc. for some good suggestions
  925. on the documentation and for providing the original C++ header file.
  926.  
  927.